package cn.dev33.satoken.action;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaCheckSafe;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.util.SaFoxUtil;
import com.csap.framework.util.CollectionsUtil;

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;

/**
 * Sa-Token 逻辑代理接口 [默认实现类]
 *
 * @author kong
 */
public class SaTokenActionDefaultImpl implements SaTokenAction {

    /**
     * 创建一个Token
     */
    @Override
    public String createToken(Object loginId, String loginType) {
        return SaManager.getConfig().getTokenStyle().getBiFunction().apply(loginId, loginType);
    }

    /**
     * 创建一个Session
     */
    @Override
    public SaSession createSession(String sessionId) {
        return new SaSession(sessionId);
    }

    /**
     * 判断：集合中是否包含指定元素（模糊匹配）
     */
    @Override
    public boolean hasElement(Collection<String> list, String element) {

        // 空集合直接返回false
        if (CollectionsUtil.isEmpty(list)) {
            return false;
        }
        // 先尝试一下简单匹配，如果可以匹配成功则无需继续模糊匹配
        if (list.contains(element)) {
            return true;
        }
        // 开始模糊匹配
        for (String patt : list) {
            if (SaFoxUtil.vagueMatch(patt, element)) {
                return true;
            }
        }
        // 走出for循环说明没有一个元素可以匹配成功
        return false;
    }

    /**
     * 对一个Method对象进行注解检查（注解鉴权内部实现）
     */
    @Override
    public void checkMethodAnnotation(Method method) {

        // 先校验 Method 所属 Class 上的注解
        validateAnnotation(method.getDeclaringClass());

        // 再校验 Method 上的注解
        validateAnnotation(method);
    }

    /**
     * 从指定元素校验注解
     *
     * @param target see note
     */
    protected void validateAnnotation(AnnotatedElement target) {

        // 校验 @SaCheckLogin 注解
        if (target.isAnnotationPresent(SaCheckLogin.class)) {
            SaCheckLogin at = target.getAnnotation(SaCheckLogin.class);
            SaManager.getStpLogic(at.type()).checkByAnnotation(at);
        }

        // 校验 @SaCheckRole 注解
        if (target.isAnnotationPresent(SaCheckRole.class)) {
            SaCheckRole at = target.getAnnotation(SaCheckRole.class);
            SaManager.getStpLogic(at.type()).checkByAnnotation(at);
        }

        // 校验 @SaCheckPermission 注解
        if (target.isAnnotationPresent(SaCheckPermission.class)) {
            SaCheckPermission at = target.getAnnotation(SaCheckPermission.class);
            SaManager.getStpLogic(at.type()).checkByAnnotation(at);
        }

        // 校验 @SaCheckSafe 注解
        if (target.isAnnotationPresent(SaCheckSafe.class)) {
            SaCheckSafe at = target.getAnnotation(SaCheckSafe.class);
            SaManager.getStpLogic(null).checkByAnnotation(at);
        }
    }

}
